/* Copyright (c) 2009-2010, Sean A.O. Harney <sharney3@gmail.com> */

#ifndef FUZZER_SYMBOL_TBL_H
#define FUZZER_SYMBOL_TBL_H

#define SYMBOL_TBL_HASHTBL_SIZE 24

typedef enum {
    SYM_TYPE_FUNCTION, SYM_TYPE_VARIABLE
} SYMBOL_TYPE;


typedef enum {
    VAR_TYPE_UNINITIALIZED,	//unknown at process-time when declared uninitialized
    VAR_TYPE_INT,
    VAR_TYPE_FLOAT,
    VAR_TYPE_STRING,
    VAR_TYPE_BOOL,
    VAR_TYPE_FUNCTION
} VAR_TYPE;

struct st_var {
    VAR_TYPE type;
    union {
	int int_val;
	float float_val;
	char *string_val;
	bool bool_val;
	char *function_val;	//symname string for function name
    } rvalue;
};


typedef struct st_symbol_tbl_entry *SYMTBL_ENT_P;

struct st_symbol_tbl_entry {
    SYMBOL_TYPE type;
    char *symname;		//same as key into hash table for this entry.
    char *filename;		// file this symbol was declared in (funcs declared at parse time, vars at process-time)
    union {
	struct {
	    LLIST_P asl;	//ptr toabstract statement list
	} function;

	struct st_var variable;

    } u;			// for lack of better name
};


typedef struct st_symbol_tbl_local_stack_node *SYMBOL_TBL_LOCAL_STACK_P;
//stack node
struct st_symbol_tbl_local_stack_node {
    HASHTBL *symbol_tbl;
    SYMBOL_TBL_LOCAL_STACK_P next;
};


/* prototypes */
HASHTBL *symbol_tbl_create(void);

// called at parse-time
bool symbol_tbl_new_entry_function(HASHTBL * symbol_tbl, char *symname,
				   char *file, LLIST_P asl);

// called at process-time of var stmts.
bool symbol_tbl_new_entry_variable_uninitialized(HASHTBL * symbol_tbl,
						 char *symname,
						 char *file);
bool symbol_tbl_new_entry_variable_int(HASHTBL * symbol_tbl, char *symname,
				       char *file, int val);
bool symbol_tbl_new_entry_variable_float(HASHTBL * symbol_tbl,
					 char *symname, char *file,
					 float val);
bool symbol_tbl_new_entry_variable_string(HASHTBL * symbol_tbl,
					  char *symname, char *file,
					  char *val);
bool symbol_tbl_new_entry_variable_bool(HASHTBL * symbol_tbl,
					char *symname, char *file,
					bool val);
bool symbol_tbl_new_entry_variable_function(HASHTBL * symbol_tbl,
					    char *symname, char *file,
					    char *func_symname);
bool symbol_tbl_new_entry_variable_from_leafexpr(HASHTBL * symbol_tbl,
						 char *symname, char *file,
						 EXPR_P leaf_expr);
SYMTBL_ENT_P symbol_tbl_get_entry(HASHTBL * symbol_tbl, char *symname);
SYMTBL_ENT_P symbol_tbl_get_entry_variable(char *symname);
SYMTBL_ENT_P symbol_tbl_get_entry_variable_fatal(char *symname);

void symbol_tbl_print_all_functions(HASHTBL * symbol_tbl, FILE * fp);

void symbol_tbl_local_stack_push(HASHTBL * symbol_tbl);
HASHTBL *symbol_tbl_local_stack_pop(void);
HASHTBL *symbol_tbl_local_stack_get_top(void);

#endif				/* FUZZER_SYMBOL_TBL_H */
